OpenRoads Designer CONNECT Edition SDK Help

Horizontal curb returns

Description

  • This is a custom interactive tool for creating alignment using points.

  • The user selects a feature definition and name, places data points, and then right-clicks to complete the command which creates a complex horizontal alignment with the given information.

  • The HorizontalAlignmentCreator class which extends DgnElementSetTool which handles different events to interact with UI, the HorizontalAlignmentCreator class overrides the events here in this tool .

Remarks

  • This sample code is a part of ManagedSDKExample which you get with SDK installation under "examples" section in SDK installation directory.

  • If you encounter any error while using DgnElementSetTool class, make sure to add a reference to Bentley.DgnDisplayNet.dll by selecting Project > Add Reference or change the projects .csproj file to add reference to this dll .

  • The default dll location will be "C:\Program Files\Bentley\OpenRoads Designer CE 10.11\OpenRoadsDesigner\Bentley.DgnDisplayNet.dll".

Source Code


//Required References
using System.Collections.Generic;
using Bentley.DgnPlatformNET;
using Bentley.DgnPlatformNET.Elements;
using Bentley.CifNET.LinearGeometry;
using Bentley.GeometryNET;
using Bentley.MstnPlatformNET;
using Bentley.CifNET.GeometryModel.SDK;
using Bentley.CifNET.GeometryModel.SDK.Edit;
using Bentley.CifNET.SDK.Edit;
using Bentley.CifNET.Formatting;

namespace ManagedSDKExample.Examples
{

    class HorizontalCurbReturns : DgnElementSetTool
    {
        List<DPoint3d> m_points = new List<DPoint3d>();

        //setup
        internal static DgnModel activeModel = Bentley.MstnPlatformNET.Session.Instance.GetActiveDgnModel();
        internal static ModelInfo info = activeModel.GetModelInfo();
        double UORS_TO_METER = 1.0 / info.UorPerMeter;

        internal static double m_defaultUnitsToMeters = FormatSettingsConstants.GetMasterUnitsToMeters();
        double MASTER_TO_METER = 1.0 * m_defaultUnitsToMeters;

        /*----------------------------------------------------------------------------------------------**/
        /* Write Function | The user is prompted to place 4 data points, representing 2 lines that cross. 
         *                  The lines are offset by a specified radius to create the center of an arc.
         *                  The program creates an arc from the given radius and returns the beginning of
         *                  the first line, the arc, and then the end of the second line.
        /*--------------+---------------+---------------+---------------+---------------+----------------*/
        internal void CreateLinesFromPoints()
        {

            //converting the point coordinates to meters
            DPoint3d firstTangentStartPoint = m_points[0];
            firstTangentStartPoint.X *= UORS_TO_METER;
            firstTangentStartPoint.Y *= UORS_TO_METER;
            firstTangentStartPoint.Z *= UORS_TO_METER;
            DPoint3d firstTangentEndPoint = m_points[1];
            firstTangentEndPoint.X *= UORS_TO_METER;
            firstTangentEndPoint.Y *= UORS_TO_METER;
            firstTangentEndPoint.Z *= UORS_TO_METER;
            DPoint3d lastTangentStartPoint = m_points[2];
            lastTangentStartPoint.X *= UORS_TO_METER;
            lastTangentStartPoint.Y *= UORS_TO_METER;
            lastTangentStartPoint.Z *= UORS_TO_METER;
            DPoint3d lastTangentEndPoint = m_points[3];
            lastTangentEndPoint.X *= UORS_TO_METER;
            lastTangentEndPoint.Y *= UORS_TO_METER;
            lastTangentEndPoint.Z *= UORS_TO_METER;

            double radius = 200 * MASTER_TO_METER;

            //uses the input points and radius to get a list of elements consisting of a starting tangent line, arc, and ending tangent line
            List<LinearElement> linElems = GetArcBetweenTwoElements(firstTangentStartPoint, firstTangentEndPoint, lastTangentStartPoint, lastTangentEndPoint, radius);

            if (linElems.Count > 0)
            {
                ConsensusConnectionEdit con = ConsensusConnectionEdit.GetActive();

                GeometricModel gm = con.GetOrCreateGeometricModel();

                if (gm == null)
                {
                    con.Close();
                    con.Dispose();
                    return;
                }

                //adds elements to alignment to display
                LinearComplex complexAlign = LinearComplex.Create1(linElems.ToArray(), false, false, 0.001);
                con.StartTransientMode();
                Bentley.CifNET.GeometryModel.SDK.Alignment al = gm.CreateAlignmentByLinearElement(complexAlign, true);
                con.PersistTransients();
            }
            else
                System.Windows.Forms.MessageBox.Show("One or both of the tangents are too short for the given radius. Try again.");

        }

        /*------------------------------------------------------------------------------------**/
        /* Creation
        /*--------------+---------------+---------------+---------------+---------------+------*/
        //Caller must check that the number of elements in the returned list is greater than 0
        //Expected input data format: meters
        public static List<LinearElement> GetArcBetweenTwoElements(Bentley.GeometryNET.DPoint3d firstTangentStartPoint, Bentley.GeometryNET.DPoint3d firstTangentEndPoint,
            Bentley.GeometryNET.DPoint3d lastTangentStartPoint, Bentley.GeometryNET.DPoint3d lastTangentEndPoint, double arcRadius)
        {
            //setup
            List<LinearElement> linElems = new List<LinearElement>();

            //creating the first tangent line            
            Line firstTangentLine = Line.Create1(firstTangentStartPoint, firstTangentEndPoint);

            //creating the last tangent line
            Line lastTangentLine = Line.Create1(lastTangentStartPoint, lastTangentEndPoint);

            //getting the angle between lines
            double angleBetweenLines = firstTangentLine.Direction - lastTangentLine.Direction;
            if (angleBetweenLines < 0) angleBetweenLines += 2 * System.Math.PI;

            Hand hand;
            Line firstTangentOffset, lastTangentOffset;
            //If the angle created by the lines is less than 180 degrees, creates a clockwise arc using offset lines in the positive direction to find the center point
            if (angleBetweenLines < System.Math.PI)
            {
                hand = Hand.Clockwise;
                firstTangentOffset = Line.Create1(firstTangentLine.GetPointAtDistanceOffset(0.0, arcRadius).Coordinates, firstTangentLine.GetPointAtDistanceOffset(firstTangentLine.Length, arcRadius).Coordinates);
                lastTangentOffset = Line.Create1(lastTangentLine.GetPointAtDistanceOffset(0.0, arcRadius).Coordinates, lastTangentLine.GetPointAtDistanceOffset(lastTangentLine.Length, arcRadius).Coordinates);
            }
            //If the angle created by the lines is greater than 180 degrees, creates a counterclockwise arc using offset lines in the negative direction to find the center point
            else
            {
                hand = Hand.CounterClockwise;
                firstTangentOffset = Line.Create1(firstTangentLine.GetPointAtDistanceOffset(0.0, -arcRadius).Coordinates, firstTangentLine.GetPointAtDistanceOffset(firstTangentLine.Length, -arcRadius).Coordinates);
                lastTangentOffset = Line.Create1(lastTangentLine.GetPointAtDistanceOffset(0.0, -arcRadius).Coordinates, lastTangentLine.GetPointAtDistanceOffset(lastTangentLine.Length, -arcRadius).Coordinates);
            }

            //getting the intersection of the offset lines
            LinearIntersectionCollection intersectionCollection = firstTangentOffset.Intersect(lastTangentOffset);
            if (intersectionCollection.Count > 0)
            {
                //the intersection of the offset lines is the center point of the arc
                Bentley.GeometryNET.DPoint3d centerPoint = intersectionCollection.Item(0).PointOn1.Coordinates;

                //getting lines perpendicular from the center point to the tangent lines to find the start and end points of the arc
                LinearPoint startPointLinear = firstTangentLine.ProjectPointOnPerpendicular(centerPoint);
                Bentley.GeometryNET.DPoint3d arcStartPoint = startPointLinear.Coordinates;
                Line startDirectionLine = Line.Create1(centerPoint, arcStartPoint);

                LinearPoint endPointLinear = lastTangentLine.ProjectPointOnPerpendicular(centerPoint);
                Bentley.GeometryNET.DPoint3d arcEndPoint = endPointLinear.Coordinates;
                Line endDirectionLine = Line.Create1(centerPoint, arcEndPoint);

                //creating the starting tangent to the arc
                Line startingTangent = Line.Create1(firstTangentStartPoint, arcStartPoint);
                linElems.Add(startingTangent);

                //creating the arc
                Bentley.CifNET.LinearGeometry.CircularArc arc = Bentley.CifNET.LinearGeometry.CircularArc.Create8(centerPoint, arcRadius, startDirectionLine.Direction, endDirectionLine.Direction, hand);
                linElems.Add(arc);

                //creating the ending tangent to the arc
                Line endLine = Line.Create1(arcEndPoint, lastTangentEndPoint);
                linElems.Add(endLine);
            }

            return linElems;
        }
        protected override void OnPostInstall()
        {
            NotificationManager.OutputPrompt("Select first data point.");
            BeginDynamics();
        }

        //adds points on click
        protected override bool OnDataButton(DgnButtonEvent ev)
        {
            if (m_points.Count == 0)
            {
                BeginDynamics();
            }

            m_points.Add(ev.Point);
            if (m_points.Count == 4)
            {
                CreateLinesFromPoints();
                EndDynamics();
                m_points.Clear();
                NotificationManager.OutputPrompt("Command complete. Select first data point or pick element selection tool to exit command.");
            }
            else
            {
                NotificationManager.OutputPrompt("Select next data point or right click to cancel the command.");
            }
            return true;
        }

        //terminates command (right click)
        protected override bool OnResetButton(DgnButtonEvent ev)
        {
            EndDynamics();
            m_points.Clear();
            NotificationManager.OutputPrompt("Command terminated. Select first data point or pick element selection tool to exit command.");
            return false;
        }

        //allows preview lines to be drawn
        protected override void OnDynamicFrame(DgnButtonEvent ev)
        {
            RedrawElems redraw = new RedrawElems();
            redraw.DrawMode = DgnDrawMode.TempDraw;
            redraw.DrawPurpose = DrawPurpose.Dynamics;
            redraw.SetViewport(ev.Viewport);

            if (m_points.Count > 1)
            {
                LineStringElement lse = new LineStringElement(Session.Instance.GetActiveDgnModel(), null, m_points.GetRange(0, 2).ToArray());
                redraw.DoRedraw(lse);
                if (m_points.Count > 3)
                {
                    LineStringElement lse2 = new LineStringElement(Session.Instance.GetActiveDgnModel(), null, m_points.GetRange(2, 2).ToArray());
                    redraw.DoRedraw(lse2);
                }
            }
        }

        protected override void OnRestartTool()
        {
            InstallNewInstance();
        }

        public override StatusInt OnElementModify(Element element)
        {
            return StatusInt.Error;
        }

        public static void InstallNewInstance()
        {
            HorizontalCurbReturns tool = new HorizontalCurbReturns();
            tool.InstallTool();
        }
    }

}